<?php
declare(strict_types=1);

namespace App\Service;

use App\Model\Dao\ChannelInfoDao;
use App\Model\Dao\ChannelMchConnLogDao;
use App\Model\Dao\MchInfoDao;
use App\Utils\CustomUtils;
use App\Utils\StringUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\ChannelMchConnDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
use Hyperf\Utils\Arr;
use MongoDB\BSON\DbPointer;

class ChannelMchConnService {

    /**
     * @Inject()
     * @var ChannelMchConnDao
     */
    private $ChannelMchConnDao;

    /**
     * @Inject()
     * @var ChannelMchConnLogDao
     */
    private $ChannelMchConnLogDao;

    /**
     * @var ChannelInfoDao
     * @Inject()
     */
    private $ChannelInfoDao;

    /**
     * @var MchInfoDao
     * @Inject()
     */
    private $MchInfoDao;

    /**
     * 设置限额
     *
     * @param $params
     *
     * @return array
     * @throws \Exception
     * @throws \Throwable
     */
    public function setTradeLimit ($params) {

        // var_dump($params);

        $mchIdList = Arr::get($params, 'mchIdList', null);
        $mchNo     = $params['mchNo'];
        $channelNo = $params['channelNo'];

        $this->_verifyMchNo($mchNo, $mchIdList);

        $this->_verifyChannelNo($channelNo);

        $info = $this->ChannelMchConnDao->getWhere(['mchNo' => $mchNo, 'channelNo' => $channelNo]);

        $update = Arr::only($params, [
            "amountMin",
            "amountLimit",
            "dayCountLimit",
            "monthCountLimit",
            "dayAmountLimit",
            "monthAmountLimit",
            "dayAmountThreshold",
            "monthAmountThreshold",
        ]);

        // 创建或更新
        if (!$info) {

            $update = array_merge($update, [
                'id'        => StringUtils::uuidV4(),
                'mchNo'     => $mchNo,
                'channelNo' => $channelNo,
                'createBy'  => $params['createBy'],
                'updateBy'  => $params['updateBy'],
            ]);
            $id     = $update['id'];
        }
        else {

            $update['updateBy'] = $params['updateBy'];
            $id                 = $info['id'];
        }

        Db::beginTransaction();

        try {

            if (!$info) {
                $this->ChannelMchConnDao->insert($update);
            }
            else {
                $this->ChannelMchConnDao->update($info['id'], $update);
            }

            $this->_addLog($id);

            $this->_onChannelMchChange($channelNo, $mchNo);

        } catch (\Throwable $e) {

            Db::rollBack();

            throw $e;
        }

        Db::commit();

        return CustomUtils::buildSuccess();
    }

    /**
     * 设置状态
     *
     * @param $params
     *
     * @return array
     * @throws \Exception
     */
    public function setStatus ($params) {

        // var_dump($params);

        $mchIdList = Arr::get($params, 'mchIdList', null);
        $mchNo     = $params['mchNo'];
        $channelNo = $params['channelNo'];

        $info = $this->ChannelMchConnDao->getWhere(['mchNo' => $mchNo, 'channelNo' => $channelNo]);

        if (!$info) {
            throw new \Exception('未找到限额记录');
        }

        $id = $info['id'];

        if (!!$params['status']) {
            $update = [
                'status'   => 1,
                'updateBy' => $params['updateBy'],
            ];
        }
        else {
            $update = [
                'status'   => 0,
                'updateBy' => $params['updateBy'],
            ];
        }

        Db::beginTransaction();

        try {

            $this->ChannelMchConnDao->update($id, $update);

            $this->_addLog($id);

            $this->_onChannelMchChange($channelNo, $mchNo);

        } catch (\Throwable $e) {
            Db::rollBack();
            throw $e;
        }

        Db::commit();

        return CustomUtils::buildSuccess();
    }

    protected function _verifyChannelNo ($channelNo) {
        $channel = $this->ChannelInfoDao->getWhere(['channelNo' => $channelNo]);

        if (!$channel) {
            throw new \Exception('通道不存在');
        }

    }

    protected function _verifyMchNo ($mchNo, $mchIdList = null) {

        $mch = $this->MchInfoDao->getWhere(['mchNo' => $mchNo]);

        if (!$mch) {
            throw new \Exception('商户不存在');
        }

        if (!is_null($mchIdList)) {
            if (!in_array($mch['id'], $mchIdList)) {
                throw new \Exception('没有该商户权限');
            }
        }
    }

    protected function _addLog ($id) {

        $raw = $this->ChannelMchConnDao->get($id);

        $update          = $raw;
        $update['id']    = StringUtils::uuidV4();
        $update['rawId'] = $raw['id'];

        $this->ChannelMchConnLogDao->insert($update);
    }

    /**
     * @param array $params
     *
     * @return array
     * @throws \Exception
     */
    public function getTradeLimitCost (array $params) {


        $mchIdList = Arr::pull($params, 'mchIdList', null);
        $mchNo     = Arr::pull($params, 'mchNo');
        $channelNo = Arr::pull($params, 'channelNo');

        $this->_verifyMchNo($mchNo, $mchIdList);
        $this->_verifyChannelNo($channelNo);

        $info = $this->ChannelMchConnDao->getWhere(['mchNo' => $mchNo, 'channelNo' => $channelNo]);

        $info = $this->_fillCostData($info);

        if (is_null($info)) {
            $info = CustomUtils::xzxEmptyObject();
        }

        return CustomUtils::buildSuccess($info);
    }

    /**
     * 补充限额使用情况
     *
     * @param $info
     *
     * @return array|null
     */
    protected function _fillCostData ($info) {

        if (!$info) {
            return null;
        }

        $info = array_merge($info, [
            'status'             => $info['status'],
            'statusTxt'          => '获取失败',
            'dayCurrentCount'    => null,
            'dayCurrentAmount'   => null,
            'monthCurrentCount'  => null,
            'monthCurrentAmount' => null,
        ]);

        if (is_null($info['status'])) {
            $info['statusTxt'] = '未配置';
            return $info;
        }

        $cost = CustomUtils::buildError('获取限额使用情况失败');
        try {
            $cost = ApplicationContext::getContainer()->get(RiskSyncService::class)->getMchChannelCost($info['channelNo'], $info['mchNo']);
        } catch (\Throwable $e) {
        }

        if (CustomUtils::isSuccess($cost)) {
            $cost = $cost['data'];

            $info = array_merge($info, Arr::only($cost, [
                'status',
                'statusTxt',
            ]), [
                'dayCurrentCount'    => (int) $cost['dayCurrentCount'],
                'dayCurrentAmount'   => (int) $cost['dayCurrentAmount'],
                'monthCurrentCount'  => (int) $cost['monthCurrentCount'],
                'monthCurrentAmount' => (int) $cost['monthCurrentAmount'],
            ]);


        }

        return $info;
    }

    /**
     * @param $params
     *
     * @return array
     */
    public function getTradeLimitCostList ($params) {

        $page  = Arr::pull($params, 'page', null);
        $limit = Arr::pull($params, 'limit', null);

        $data = $this->ChannelMchConnDao->getTradeLimitCostList($params, $page, $limit);

        // 补充限额使用情况
        $list = $data['list'];
        foreach ($list as $k => $item) {
            $list[$k] = $this->_fillCostData($item);
        }

        $data['list'] = $list;

        return CustomUtils::buildSuccess($data);
    }


    /**
     * @param $channelNo
     * @param $mchNo
     *
     * @throws \Exception
     */
    protected function _onChannelMchChange ($channelNo, $mchNo) {

        // 更新通道缓存
        ApplicationContext::getContainer()->get(RiskSyncService::class)->syncChannelCollection([$channelNo]);
    }

}
